package com.chaos.framework.model.helper;


import cn.hutool.core.util.ObjectUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Function;

/**
 * @author 肖晓霖
 * <p>Title: MapKit</p>
 * <p>Description: Map相关工具类</p>
 *
 */
public class MapHelper {
    private MapHelper() {
    }
    
    public static <K, V> void setValue(Map<K, V> map, K key, Function<V, V> setFunction) {
        map.compute(key, (k, v) -> setFunction.apply(v));
    }
    
    public static <K, E, R> List<R> convertToList(Map<K, E> listMap, BiFunction<K, E, R> operator) {
        List<R> result = new ArrayList<>(listMap.size());
        if (ObjectUtil.isEmpty(listMap)) {
            return result;
        }
        listMap.forEach((k, v) -> result.add(operator.apply(k, v)));
        return result;
    }

    public static <K, E, R> Map<K, R> convert(Map<K, E> listMap, BiFunction<K, E, R> valueOperator) {
        return convert(listMap, valueOperator, (k, v) -> k);
    }

    public static <K, E, K2, R> Map<K2, R> convert(Map<K, E> listMap, BiFunction<K, E, R> valueOperator, BiFunction<K, E, K2> keyOperator) {
        Map<K2, R> result = new HashMap<>(listMap.size());
        listMap.forEach((k, v) -> result.put(keyOperator.apply(k, v), valueOperator.apply(k, v)));
        return result;
    }


    public static <K, V> void removeIf(Map<K, V> map, BiPredicate<K, V> predicate) {
        if (ObjectUtil.isEmpty(map)) {
            return;
        }
        map.entrySet().removeIf(entry -> predicate.test(entry.getKey(), entry.getValue()));
    }

    public static <K, V> Optional<Map.Entry<K, V>> find(Map<K, V> map, BiPredicate<K, V> predicate) {
        for (Map.Entry<K, V> kvEntry : map.entrySet()) {
            if (predicate.test(kvEntry.getKey(), kvEntry.getValue())) {
                return Optional.of(kvEntry);
            }
        }
        return Optional.empty();
    }
}
